class_name TweenTest extends Node2D

## 补间动画类型
enum TweenerType {
	PROPERTY_TWEENER,
	INTERVAL_TWEENER,
	CALLBACK_TWEENER,
	METHOD_TWEENER,
}

## 队列模式
enum TweenerQueueMode {
	CHAIN,
	PARALLEL,
}

@onready var option_button_tweener_type: OptionButton = $PanelOption/OptionButtonTweenerType as OptionButton
@onready var spin_box_duration: SpinBox = $PanelOption/SpinBoxDuration as SpinBox
@onready var spin_box_delay: SpinBox = $PanelOption/SpinBoxDelay as SpinBox
@onready var option_button_ease_type: OptionButton = $PanelOption/OptionButtonEaseType as OptionButton
@onready var option_button_transition_type: OptionButton = $PanelOption/OptionButtonTransitionType as OptionButton
@onready var option_button_queue_mode: OptionButton = $PanelOption/OptionButtonQueueMode as OptionButton
@onready var option_button_process_mode: OptionButton = $PanelOption/OptionButtonProcessMode as OptionButton
@onready var option_button_pause_mode: OptionButton = $PanelOption/OptionButtonPauseMode as OptionButton
@onready var spin_box_loop: SpinBox = $PanelOption/SpinBoxLoop as SpinBox
@onready var spin_box_speed_scale: SpinBox = $PanelOption/SpinBoxSpeedScale as SpinBox
@onready var item_list_tweeners: ItemList = $PanelOption/ItemListTweeners as ItemList
@onready var button_delete: Button = $PanelOption/ButtonDelete as Button
@onready var button_clear: Button = $PanelOption/ButtonClear as Button
@onready var button_play: Button = $ButtonPlay as Button
@onready var button_pause: Button = $ButtonPause as Button
@onready var button_stop: Button = $ButtonStop as Button
@onready var button_kill: Button = $ButtonKill as Button
@onready var icon: Sprite2D = $PanelTween/Icon as Sprite2D
@onready var panel_tween: Panel = $PanelTween as Panel
@onready var line_2d_time: Line2D = $PanelTween/Line2DTime as Line2D
@onready var label_time: Label = $PanelTween/LabelTime as Label
@onready var line_2dy: Line2D = $PanelTween/Line2DY as Line2D
@onready var label_y: Label = $PanelTween/LabelY as Label
@onready var line_2d_tween: Line2D = $PanelTween/Line2DTween as Line2D


## 正在使用的动画
var tween: Tween = null
## 图标的起始位置的y坐标
var from_y: float
## 图标的结束位置的y坐标
var final_y: float
## 图标的结束位置的x坐标
var final_x: float
## 随机数生成器
var random: RandomNumberGenerator
## 动画的总时长
var tween_total_time: float

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	from_y = panel_tween.size.y / 2
	icon.position = Vector2(0, from_y)
	final_y = 0.0
	final_x = panel_tween.size.x - icon.texture.get_size().x * icon.scale.x
	random = RandomNumberGenerator.new()
	tween_total_time = 0.0
	_adjust_axis()


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta: float) -> void:
	if tween == null or not tween.is_valid() or not tween.is_running():
		return
	_set_icon_position_x(_get_icon_position_x())
	line_2d_tween.add_point(icon.position)


## 选择补间动画类型时，切换相关选项的状态
func _on_option_button_tweener_type_item_selected(index: int) -> void:
	if index == TweenerType.INTERVAL_TWEENER or index == TweenerType.CALLBACK_TWEENER:
		option_button_ease_type.disabled = true
		option_button_transition_type.disabled = true
	else:
		option_button_ease_type.disabled = false
		option_button_transition_type.disabled = false


## 选择队列中的补间动画时，修改删除按钮的状态
func _on_item_list_tweeners_item_selected(_index: int) -> void:
	button_delete.disabled = not item_list_tweeners.is_anything_selected()


## 添加补间动画到队列中
func _on_button_add_pressed() -> void:
	var tweener_info: TweenerInfo = _get_current_tweener_info()
	var index:int = item_list_tweeners.add_item(str(tweener_info))
	item_list_tweeners.set_item_metadata(index, tweener_info)
	button_clear.disabled = false
	button_play.disabled = false


## 删除选中的补间动画
func _on_button_delete_pressed() -> void:
	if not item_list_tweeners.is_anything_selected():
		return
	var selected_items: PackedInt32Array = item_list_tweeners.get_selected_items()
	selected_items.reverse()
	for index in selected_items:
		item_list_tweeners.remove_item(index)
	button_delete.disabled = true
	button_clear.disabled = item_list_tweeners.item_count == 0
	button_play.disabled = item_list_tweeners.item_count == 0


## 清空队列中的补间动画
func _on_button_clear_pressed() -> void:
	item_list_tweeners.clear()
	button_delete.disabled = true
	button_clear.disabled = true
	button_play.disabled = true


## 播放动画
func _on_button_play_pressed() -> void:
	if tween == null or not tween.is_valid():
		_create_tween_queue()
		line_2d_tween.clear_points()
	if tween != null and tween.is_valid():
		var is_running: bool = tween.is_running()
		tween.play()
		if is_running:
			print(Time.get_datetime_string_from_system(), "\t继续播放动画。")
		else:
			print(Time.get_datetime_string_from_system(), "\t开始播放动画。")
	button_play.disabled = true
	button_pause.disabled = false
	button_stop.disabled = false
	button_kill.disabled = false


## 暂停动画
func _on_button_pause_pressed() -> void:
	if tween != null and tween.is_valid() and tween.is_running():
		tween.pause()
	button_play.disabled = false
	button_pause.disabled = true
	button_stop.disabled = false
	button_kill.disabled = false


## 停止动画
func _on_button_stop_pressed() -> void:
	if tween != null and tween.is_valid() and tween.is_running():
		tween.stop()
	button_play.disabled = false
	button_pause.disabled = true
	button_stop.disabled = true
	button_kill.disabled = false


## 终止动画
func _on_button_kill_pressed() -> void:
	if tween != null and tween.is_valid():
		tween.kill()
		tween = null
	button_play.disabled = false
	button_pause.disabled = true
	button_stop.disabled = true
	button_kill.disabled = true
	

## 创建补间动画队列
func _create_tween_queue() -> void:
	if item_list_tweeners.item_count == 0:
		return
	tween = create_tween()
	var tween_time: float = 0.0
	for index in item_list_tweeners.item_count:
		var tweener_info: TweenerInfo = item_list_tweeners.get_item_metadata(index) as TweenerInfo
		if not tweener_info:
			continue
		if tweener_info.queue_mode == TweenerQueueMode.CHAIN:
			tween.chain()
		else:
			tween.parallel()
		match tweener_info.tweener_type:
			TweenerType.PROPERTY_TWEENER:
				var property_tweener: PropertyTweener = tween.tween_property(icon, "position:y", final_y, tweener_info.duration)
				property_tweener.from(from_y)
				property_tweener.set_delay(tweener_info.delay)
				property_tweener.set_ease(tweener_info.ease_type)
				property_tweener.set_trans(tweener_info.transition_type)
				tween_time += tweener_info.duration + tweener_info.delay
			TweenerType.INTERVAL_TWEENER:
				tween.tween_interval(tweener_info.duration)
				tween_time += tweener_info.duration
			TweenerType.CALLBACK_TWEENER:
				var callback_tweener: CallbackTweener = tween.tween_callback(_set_icon_random_position_y)
				callback_tweener.set_delay(tweener_info.delay)
				tween_time += tweener_info.delay
			TweenerType.METHOD_TWEENER:
				var method_tweener: MethodTweener = tween.tween_method(_set_icon_position_y, from_y, final_y, tweener_info.duration)
				method_tweener.set_delay(tweener_info.delay)
				method_tweener.set_ease(tweener_info.ease_type)
				method_tweener.set_trans(tweener_info.transition_type)
				tween_time += tweener_info.duration + tweener_info.delay
	tween.set_process_mode(option_button_process_mode.get_selected_id())
	tween.set_pause_mode(option_button_pause_mode.get_selected_id())
	var loops_count: int = int(spin_box_loop.value)
	tween.set_loops(loops_count)
	tween.set_speed_scale(spin_box_speed_scale.value)
	if is_zero_approx(spin_box_loop.value):
		tween_total_time = tween_time
	else:
		tween_total_time = tween_time * loops_count
	tween.finished.connect(_on_tween_finished)
	tween.loop_finished.connect(_on_tween_loop_finished)
	tween.step_finished.connect(_on_tween_step_finished)


## 获取当前正在编辑TweenerInfo
func _get_current_tweener_info() -> TweenerInfo:
	return TweenerInfo.new(option_button_tweener_type.get_selected_id(),
			spin_box_duration.value,
			spin_box_delay.value,
			option_button_ease_type.get_selected_id(),
			option_button_transition_type.get_selected_id(),
			option_button_queue_mode.get_selected_id())


## 回调函数：获取用于显示图标的随机位置的y坐标，并将图标移动到该位置
func _set_icon_random_position_y() -> void:
	var _y = random.randf_range(0, final_y)
	_set_icon_position_y(_y)
	

## 方法函数：设置图标的位置的y坐标
func _set_icon_position_y(_y: float) -> void:
	icon.position.y = _y


## 设置图标的位置的x坐标：x坐标代表动画运行的时间
func _set_icon_position_x(x: float) -> void:
	icon.position.x = x
	

## 获取图标的位置的x坐标：x坐标代表动画运行的时间
func _get_icon_position_x() -> float:
	var x: float = icon.position.x
	if is_zero_approx(tween_total_time):
		return x
	var total_elapsed_time: float = tween.get_total_elapsed_time()
	var x_min: float = 0.0
	x = (final_x - x_min) * total_elapsed_time / tween_total_time
	return min(x, final_x)

## 完成动画
func _on_tween_finished() -> void:
	tween_total_time = 0.0
	print(Time.get_datetime_string_from_system(),"\t完成动画。")
	button_play.disabled = false
	button_pause.disabled = true
	button_stop.disabled = true
	button_kill.disabled = true


## 完成动画循环
func _on_tween_loop_finished(loop_count: int) -> void:
	print(Time.get_datetime_string_from_system(),"\t完成第", loop_count, "次动画循环。")
	
	
## 完成动画步骤
func _on_tween_step_finished(idx: int) -> void:
	print(Time.get_datetime_string_from_system(),"\t完成第", idx, "步动画步骤。")


## 添加时间轴的点
func _add_axis_time_points() -> void:
	var y: float = panel_tween.size.y / 2.0
	line_2d_time.add_point(Vector2(0.0, y))
	line_2d_time.add_point(Vector2(panel_tween.size.x, y))
		

## 添加y轴的点
func _add_axis_y_points() -> void:
	line_2dy.add_point(Vector2.ZERO)
	line_2dy.add_point(Vector2(0.0, panel_tween.size.y))
		
	
## 调整时间轴的标签
func _adjust_axis_time_label() -> void:
	label_time.position.x = panel_tween.size.x - label_time.size.x -5.0
	label_time.position.y = panel_tween.size.y / 2.0 + 5.0
	
	
func _adjust_axis_y_label() -> void:
	label_y.position.x = -1.0 * (label_y.size.x + 5.0)
	label_y.position.y = -5.0
	

## 调整坐标
func _adjust_axis() -> void:
	_add_axis_time_points()
	_add_axis_y_points()
	_adjust_axis_time_label()
	_adjust_axis_y_label()
